﻿using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using static 摸鱼.全局类;
using Point = OpenCvSharp.Point;
using Size = System.Drawing.Size;

namespace 摸鱼
{
    public class 前景窗口 : Form
    {
        // 静态成员
        public static Mat 画板;
        public static IntPtr 句柄;
        public static 前景窗口 窗体;
        public static ConcurrentQueue<Action> 任务s = new();
        public static bool 开启 = false;
        private static MainWindow 主窗体;

        // 矩形管理 - 使用更精确的键和自动清理
        private static ConcurrentDictionary<long, (Rect 矩形, DateTime 时间, int 分类id)> 矩形字典 = new();
        private static readonly object 绘制锁 = new object();
        private static long 矩形计数器 = 0;

        // 控件
        private PictureBox pictureBox;
        private System.Windows.Forms.Timer 刷新定时器;

        public static void Send(核心._数据._方法data moyuWait, Action action)
        {
            任务s.Enqueue(action + moyuWait.信号.Set);
            moyuWait.信号.Wait();
        }

        public static void Post(Action action)
        {
            任务s.Enqueue(action);
        }

        public 前景窗口(MainWindow mainWindow)
        {
            InitializeComponent();
            主窗体 = mainWindow;
            主窗体.Closing += (s, e) => this.Close();

            // 初始化定时器
            初始化定时器();
        }

        [System.Diagnostics.DebuggerStepThrough]
        private void InitializeComponent()
        {
            pictureBox = new PictureBox();
            ((System.ComponentModel.ISupportInitialize)pictureBox).BeginInit();
            SuspendLayout();

            // pictureBox
            pictureBox.Dock = DockStyle.Fill;
            pictureBox.Name = "pictureBox";
            pictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
            pictureBox.TabStop = false;

            // 前景窗口
            BackColor = Color.FromArgb(0, 0, 0);
            BackgroundImageLayout = ImageLayout.Stretch;
            ClientSize = new Size(800, 600);
            Controls.Add(pictureBox);
            DoubleBuffered = true;
            FormBorderStyle = FormBorderStyle.None;
            Name = "前景窗口";
            ShowIcon = false;
            ShowInTaskbar = false;
            Text = "Moyu前景窗口";
            TransparencyKey = Color.FromArgb(0, 0, 0);
            WindowState = FormWindowState.Maximized;
            TopMost = true;

            Shown += 窗口显示;

            // 设置窗口样式
            int 窗体信息 = Win32.GetWindowLong(Handle, Win32.GWL_EXSTYLE);
            Win32.SetWindowLong(Handle, Win32.GWL_EXSTYLE, 窗体信息 | Win32.WS_EX_NOACTIVATE);

            ((System.ComponentModel.ISupportInitialize)pictureBox).EndInit();
            ResumeLayout(false);
        }
        private void 窗口显示(object? sender, EventArgs? e)
        {
            TopMost = true;
        }
        public static void 绘制(List<Rect> 矩形列表, List<int> 类别列表)
        {
            Post(() =>
            {
                lock (绘制锁)
                {
                    // 正确的调用方式：将两个列表转换为参数
                    var 新矩形数据 = 矩形列表.Zip(类别列表, (矩形, 分类id) => (矩形, 分类id)).ToList();
                    var 处理后的矩形 = 与现有矩形合并(新矩形数据);

                    // 更新矩形字典 - 使用唯一ID作为键
                    foreach (var (矩形, 分类id) in 处理后的矩形)
                    {
                        long 矩形ID = System.Threading.Interlocked.Increment(ref 矩形计数器);
                        矩形字典[矩形ID] = (矩形, DateTime.Now, 分类id);
                    }

                    // 立即强制重绘
                    窗体.强制重绘();
                }
            });
        }
        private static List<(Rect 矩形, int 分类id)> 与现有矩形合并(List<(Rect 矩形, int 分类id)> 新矩形列表)
        {
            if (矩形字典.IsEmpty) return 新矩形列表;

            // 创建空间网格来加速相交检测
            var 空间网格 = new Dictionary<(int, int), List<(Rect 矩形, int 分类id)>>();
            int 网格大小 = 100; // 每个网格100x100像素

            // 将现有矩形加入网格
            foreach (var (矩形, 时间, 分类id) in 矩形字典.Values)
            {
                添加矩形到网格(矩形, 分类id, 空间网格, 网格大小);
            }

            // 将新矩形加入网格并合并
            var 最终结果 = new List<(Rect 矩形, int 分类id)>();
            var 已合并矩形 = new HashSet<Rect>();

            foreach (var (新矩形, 分类id) in 新矩形列表)
            {
                if (已合并矩形.Contains(新矩形)) continue;

                var 相交矩形组 = 查找相交矩形组(新矩形, 空间网格, 网格大小, 已合并矩形);

                if (相交矩形组.Count > 0)
                {
                    // 合并所有相交的矩形（包括新矩形）
                    相交矩形组.Add((新矩形, 分类id));

                    // 标记这些矩形为已合并
                    foreach (var 矩形 in 相交矩形组)
                    {
                        已合并矩形.Add(矩形.矩形);
                    }

                    // 计算合并后的矩形
                    Rect 合并矩形 = 计算合并矩形(相交矩形组.Select(x => x.矩形).ToList());

                    // 确定主要类别
                    int 主要类别 = 相交矩形组.GroupBy(x => x.分类id)
                                      .OrderByDescending(g => g.Count())
                                      .First().Key;

                    最终结果.Add((合并矩形, 主要类别));

                    // 从网格中移除已合并的矩形
                    foreach (var 矩形 in 相交矩形组)
                    {
                        从网格中移除矩形(矩形.矩形, 空间网格, 网格大小);
                    }

                    // 将合并后的矩形加入网格
                    添加矩形到网格(合并矩形, 主要类别, 空间网格, 网格大小);
                }
                else
                {
                    最终结果.Add((新矩形, 分类id));
                    添加矩形到网格(新矩形, 分类id, 空间网格, 网格大小);
                }
            }

            return 最终结果;
        }

        private static List<(Rect 矩形, int 分类id)> 查找相交矩形组(Rect 目标矩形,
            Dictionary<(int, int), List<(Rect 矩形, int 分类id)>> 网格, int 网格大小, HashSet<Rect> 已合并矩形)
        {
            var 结果 = new List<(Rect 矩形, int 分类id)>();
            var 待检查队列 = new Queue<Rect>();
            待检查队列.Enqueue(目标矩形);

            var 已检查矩形 = new HashSet<Rect>();
            已检查矩形.Add(目标矩形);

            while (待检查队列.Count > 0)
            {
                var 当前矩形 = 待检查队列.Dequeue();

                // 查找与当前矩形相交的所有矩形
                var 相交矩形 = 查找相交矩形(当前矩形, 网格, 网格大小);

                foreach (var 相交 in 相交矩形)
                {
                    if (!已检查矩形.Contains(相交.矩形) && !已合并矩形.Contains(相交.矩形))
                    {
                        结果.Add(相交);
                        已检查矩形.Add(相交.矩形);
                        待检查队列.Enqueue(相交.矩形);
                    }
                }
            }

            return 结果;
        }

        private static List<(Rect 矩形, int 分类id)> 查找相交矩形(Rect 目标矩形,
            Dictionary<(int, int), List<(Rect 矩形, int 分类id)>> 网格, int 网格大小)
        {
            var 结果 = new List<(Rect 矩形, int 分类id)>();
            var 已处理 = new HashSet<Rect>();

            int 起始X = 目标矩形.X / 网格大小;
            int 结束X = (目标矩形.X + 目标矩形.Width) / 网格大小;
            int 起始Y = 目标矩形.Y / 网格大小;
            int 结束Y = (目标矩形.Y + 目标矩形.Height) / 网格大小;

            for (int x = 起始X; x <= 结束X; x++)
            {
                for (int y = 起始Y; y <= 结束Y; y++)
                {
                    var 网格键 = (x, y);
                    if (网格.ContainsKey(网格键))
                    {
                        foreach (var 矩形 in 网格[网格键])
                        {
                            if (!已处理.Contains(矩形.矩形) &&
                                矩形是否相交或相近(目标矩形, 矩形.矩形, 10))
                            {
                                结果.Add(矩形);
                                已处理.Add(矩形.矩形);
                            }
                        }
                    }
                }
            }

            return 结果;
        }

        private static void 添加矩形到网格(Rect 矩形, int 分类id,
            Dictionary<(int, int), List<(Rect 矩形, int 分类id)>> 网格, int 网格大小)
        {
            int 起始X = 矩形.X / 网格大小;
            int 结束X = (矩形.X + 矩形.Width) / 网格大小;
            int 起始Y = 矩形.Y / 网格大小;
            int 结束Y = (矩形.Y + 矩形.Height) / 网格大小;

            for (int x = 起始X; x <= 结束X; x++)
            {
                for (int y = 起始Y; y <= 结束Y; y++)
                {
                    var 网格键 = (x, y);
                    if (!网格.ContainsKey(网格键))
                        网格[网格键] = new List<(Rect 矩形, int 分类id)>();

                    网格[网格键].Add((矩形, 分类id));
                }
            }
        }

        private static void 从网格中移除矩形(Rect 矩形,
            Dictionary<(int, int), List<(Rect 矩形, int 分类id)>> 网格, int 网格大小)
        {
            int 起始X = 矩形.X / 网格大小;
            int 结束X = (矩形.X + 矩形.Width) / 网格大小;
            int 起始Y = 矩形.Y / 网格大小;
            int 结束Y = (矩形.Y + 矩形.Height) / 网格大小;

            for (int x = 起始X; x <= 结束X; x++)
            {
                for (int y = 起始Y; y <= 结束Y; y++)
                {
                    var 网格键 = (x, y);
                    if (网格.ContainsKey(网格键))
                    {
                        // 移除指定的矩形
                        网格[网格键].RemoveAll(item => item.矩形 == 矩形);

                        // 如果网格为空，移除该网格键
                        if (网格[网格键].Count == 0)
                        {
                            网格.Remove(网格键);
                        }
                    }
                }
            }
        }
        private static bool 矩形是否相交或相近(Rect rect1, Rect rect2, int 阈值)
        {
            // 检查是否相交
            if (rect1.IntersectsWith(rect2))
                return true;

            // 检查是否相近
            Point 中心1 = new Point(rect1.X + rect1.Width / 2, rect1.Y + rect1.Height / 2);
            Point 中心2 = new Point(rect2.X + rect2.Width / 2, rect2.Y + rect2.Height / 2);

            double 距离 = Math.Sqrt(Math.Pow(中心1.X - 中心2.X, 2) + Math.Pow(中心1.Y - 中心2.Y, 2));
            return 距离 <= 阈值;
        }
        private static Rect 计算合并矩形(List<Rect> 矩形组)
        {
            if (矩形组.Count == 1) return 矩形组[0];

            int minX = 矩形组.Min(r => r.X);
            int minY = 矩形组.Min(r => r.Y);
            int maxX = 矩形组.Max(r => r.X + r.Width);
            int maxY = 矩形组.Max(r => r.Y + r.Height);

            return new Rect(minX, minY, maxX - minX, maxY - minY);
        }

        // 初始化定时器 - 修正版本
        private void 初始化定时器()
        {
            刷新定时器 = new System.Windows.Forms.Timer();
            刷新定时器.Interval = 50; // 20fps，更频繁的清理
            刷新定时器.Tick += (s, e) => 定时刷新();
            刷新定时器.Start();
        }
        private const float 存活时间阈值 = 0.3f;
        private void 定时刷新()
        {
            bool 需要重绘 = false;
            var 当前时间 = DateTime.Now;
            var 待删除键 = new List<long>();

            // 检查所有矩形的过期状态
            foreach (var kvp in 矩形字典)
            {
                var (矩形, 时间, 分类id) = kvp.Value;
                double 存活时间 = (当前时间 - 时间).TotalSeconds;

                // 超过1秒就标记为删除
                if (存活时间 > 存活时间阈值)
                {
                    待删除键.Add(kvp.Key);
                    需要重绘 = true;
                }
            }

            // 删除过期矩形
            if (待删除键.Count > 0)
            {
                lock (绘制锁)
                {
                    foreach (var 键 in 待删除键)
                    {
                        矩形字典.TryRemove(键, out _);
                    }
                }
            }

            // 如果有矩形或者刚删除了矩形，就重绘
            if (!矩形字典.IsEmpty || 需要重绘)
            {
                强制重绘();
            }
        }

        private void 强制重绘()
        {
            lock (绘制锁)
            {
                if (矩形字典.IsEmpty)
                {
                    // 清空显示
                    清空显示();
                    return;
                }

                // 创建新的画板
                using (Mat 新画板 = new Mat(屏幕高度, 屏幕宽度, MatType.CV_8UC3, new Scalar(0, 0, 0)))
                {
                    var 当前时间 = DateTime.Now;

                    // 绘制所有活跃的矩形
                    foreach (var (矩形, 时间, 分类id) in 矩形字典.Values)
                    {
                        double 存活时间 = (当前时间 - 时间).TotalSeconds;
                        double 新鲜度 = Math.Max(0, 1 - (存活时间 / 存活时间阈值)); // 1秒内完全消失

                        // 如果已经过期，跳过绘制（理论上不应该发生，因为定时器会清理）
                        if (新鲜度 <= 0) continue;

                        byte 颜色值 = (byte)(255 * 新鲜度);
                        Scalar 颜色 = new Scalar(0, 颜色值, 255 - 颜色值);

                        Cv2.Rectangle(新画板, 矩形, 颜色, 2, LineTypes.AntiAlias);
                        Cv2.PutText(新画板, $"ID:{分类id}", new Point(矩形.X, 矩形.Y - 5),
                            HersheyFonts.HersheySimplex, 0.6, 颜色, 1);
                    }

                    // 更新PictureBox
                    if (!新画板.Empty() && pictureBox != null)
                    {
                        更新图片显示(新画板);
                    }
                    else
                    {
                        清空显示();
                    }
                }
            }
        }

        private void 更新图片显示(Mat 图像)
        {
            try
            {
                using (var bitmap = BitmapConverter.ToBitmap(图像))
                {
                    if (pictureBox.InvokeRequired)
                    {
                        pictureBox.Invoke(new Action(() =>
                        {
                            if (pictureBox.Image != null)
                                pictureBox.Image.Dispose();
                            pictureBox.Image = (Bitmap)bitmap.Clone();
                        }));
                    }
                    else
                    {
                        if (pictureBox.Image != null)
                            pictureBox.Image.Dispose();
                        pictureBox.Image = (Bitmap)bitmap.Clone();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"更新图片显示错误: {ex.Message}");
            }
        }

        private void 清空显示()
        {
            if (pictureBox != null)
            {
                if (pictureBox.InvokeRequired)
                {
                    pictureBox.Invoke(new Action(() =>
                    {
                        if (pictureBox.Image != null)
                        {
                            pictureBox.Image.Dispose();
                            pictureBox.Image = null;
                        }
                    }));
                }
                else
                {
                    if (pictureBox.Image != null)
                    {
                        pictureBox.Image.Dispose();
                        pictureBox.Image = null;
                    }
                }
            }
        }

        // 清空所有矩形
        public static void 清空绘制()
        {
            Post(() =>
            {
                lock (绘制锁)
                {
                    矩形字典.Clear();
                    窗体.清空显示();
                }
            });
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                刷新定时器?.Stop();
                刷新定时器?.Dispose();
                画板?.Dispose();
                清空显示();
            }
            base.Dispose(disposing);
        }
    }
}